package com.ds.infra.ibatis.handler;

import com.ds.infra.ibatis.reflection.MetaObject;
import com.ds.infra.ibatis.session.Configuration;
import com.ds.infra.ibatis.mapping.MappedStatement;
import com.ds.infra.ibatis.type.TypeHandler;
import com.ds.infra.ibatis.type.TypeHandlerRegistry;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import java.util.Map;

/**
 * 作用：参数处理器，用于设置PreparedStatement的参数。
 *
 * @author WeiShaoying
 */
@SuppressWarnings("unchecked")
public class DefaultParameterHandler implements ParameterHandler {

    private final Configuration configuration;
    private final Object parameterObject;
    private final MappedStatement mappedStatement;
    private final TypeHandlerRegistry typeHandlerRegistry;

    public DefaultParameterHandler(Configuration configuration,
                                   Object parameterObject,
                                   MappedStatement mappedStatement) {
        this.configuration = configuration;
        this.parameterObject = parameterObject;
        this.mappedStatement = mappedStatement;
        this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
    }

    @Override
    public void setParameters(PreparedStatement ps) throws SQLException {
        List<String> paramNames = mappedStatement.getParameterNames();
        if (paramNames.isEmpty() || parameterObject == null) {
            return;
        }

        // 处理基本类型参数
        if (isSimpleType(parameterObject.getClass())) {
            if (paramNames.size() == 1) {
                setSimpleParameter(ps, 1, parameterObject);
            }
            return;
        }

        MetaObject metaObject = configuration.newMetaObject(parameterObject);

        for (int i = 0; i < paramNames.size(); i++) {
            String paramName = paramNames.get(i);
            Object value;

            if (parameterObject instanceof Map) {
                value = ((Map<?, ?>) parameterObject).get(paramName);
            } else {
                value = metaObject.getValue(paramName);
            }

            setSimpleParameter(ps, i + 1, value);
        }
    }

    private boolean isSimpleType(Class<?> clazz) {
        return clazz.isPrimitive() ||
                clazz == String.class ||
                Number.class.isAssignableFrom(clazz) ||
                clazz == Boolean.class ||
                clazz == Character.class;
    }

    private void setSimpleParameter(PreparedStatement ps, int parameterIndex, Object value) throws SQLException {
        if (value == null) {
            ps.setNull(parameterIndex, Types.NULL);
        } else {
            // 使用类型处理器设置参数
            TypeHandler typeHandler = typeHandlerRegistry.getTypeHandler(value.getClass());
            if (typeHandler != null) {
                typeHandler.setParameter(ps, parameterIndex, value);
            } else {
                ps.setObject(parameterIndex, value);
            }
        }
    }
}
